package com.ibm.risk.irmp.common.utils;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CmdExecutionUtils {
    public static String executCmd(String cmd, long maxSeconds, String... args) {
        String[] shellCmds = cmd.split(" ");
        String[] cmdarray = new String[shellCmds.length + args.length];
        int i = 0;
        for (String sc : shellCmds) {
            cmdarray[i++] = sc;
        }
        for (String sc : args) {
            cmdarray[i++] = sc;
        }
        return execShell(cmdarray, maxSeconds);
    }

    static String execShell(String[] scripts, long maxSeconds) {
        // 创建CallableStatement对象
        log.info("execShell {}", Arrays.asList(scripts));
        StringBuilder sOut = new StringBuilder();
        StringBuilder sErr = new StringBuilder();
        ShellOutputReader stdReader = new ShellOutputReader(sOut);
        ShellOutputReader errReader = new ShellOutputReader(sErr);
        int result;
        result = runCmd(scripts, maxSeconds, stdReader, errReader);
        if (sErr.length() > 0) {
            String errMsg = sErr.toString();
            log.error("shell command - err out: {}", errMsg);
            throw new RuntimeException("shell command error:\r\n" + errMsg);
        }
        String out = sOut.toString();
        log.info("shell command - msg out: {}", out);
        if (result != 0) {
            throw new RuntimeException("shell command returned :" + result);
        }
        return out;
    }

    public static int runCmd(String[] scripts, long maxSeconds, ShellOutputReader stdReader, ShellOutputReader errReader) {
        int result;
        try {
            Process p = Runtime.getRuntime().exec(scripts);
            stdReader.setInputStream(p.getInputStream());
            errReader.setInputStream(p.getInputStream());
            new Thread(stdReader).start();
            new Thread(errReader).start();

            p.waitFor(maxSeconds, TimeUnit.SECONDS);
            result = p.exitValue();
            log.info("shell command - shell process returned: {}", result);
        } catch (Exception e) {
            log.error("Error to execute command.", e);
            throw new RuntimeException("Error to execute command:" + scripts, e);
        }
        return result;
    }

    static class ShellOutputReader implements Runnable {
        protected Log logger = LogFactory.getLog(getClass());
        @Setter
        private InputStream inputStream;
        private StringBuilder buffer;

        public ShellOutputReader(StringBuilder buffer) {
            this.buffer = buffer;
        }

        @Override
        public void run() {
            try (BufferedReader inReader = new BufferedReader(new InputStreamReader(inputStream, System.getProperty("sun.jnu.encoding")))) {
                String line = null;
                while ((line = inReader.readLine()) != null) {
                    buffer.append(line).append("\r\n");
                }
            } catch (IOException e) {
                logger.error("exception", e);
            }

        }
    }
}
